/*
 router.go
 Created by hupfei on 2019-07-17
*/

package model

import (
	"database/sql"
	"fmt"
	"github.com/jmoiron/sqlx"
	"strconv"
	"zimuzu_cvn_web_api/config"
	. "zimuzu_cvn_web_api/pkg/e"
)

type ChartGlobal struct {
	Time       string  `json:"time"`
	Total      int64   `json:"total"`
	Cvnt       float64 `json:"cvn" db:"cvn"`
	OnlineTime int     `json:"online_time" db:"online_time"`
}

type ChartUserParams struct {
	ShowType int `form:"show_type" json:"show_type,omitempty"`
	NodeId   int `form:"node_id" json:"node_id"`
	Source   int `form:"source" json:"source"`
}

type ChartRouter struct {
	Time        string  `json:"time" db:"time"`
	Total       string  `json:"total" db:"total"`
	TotalFormat string  `json:"totalFormat" db:"totalFormat"`
	Cvnt        float64 `json:"cvnt" db:"cvnt"`
	OnlineTime  int64   `json:"onlineTime,omitempty" db:"onlineTime"`
	Status      float64 `json:"status,omitempty" db:"status"`
}

//查询用户路由器数量
//source 1 全部  2 挖矿中的
func GetUserNodeNums(uid int64, source int, Type int) (Nums int64, err error) {
	if source == 1 {
		if Type == NodeTypeALL {
			err = sqlx.Get(config.C.DB.DB, &Nums, "SELECT count(*) FROM mg_node where uid = ? AND status != 2", uid)
		} else {
			err = sqlx.Get(config.C.DB.DB, &Nums, "SELECT count(*) FROM mg_node where uid = ? AND type = ? AND status != 2", uid, Type)
		}
	} else {
		if Type == NodeTypeALL {
			err = sqlx.Get(config.C.DB.DB, &Nums, "SELECT count(*) FROM mg_node where uid = ? and status = 1", uid)
		} else {
			err = sqlx.Get(config.C.DB.DB, &Nums, "SELECT count(*) FROM mg_node where uid = ? and status = 1 AND type = ?", uid, Type)
		}
	}
	if err == sql.ErrNoRows {
		return 0, nil
	}
	if err != nil {
		Log("error", uid, "查询用户节点数量失败", err.Error())
		return 0, err
	}
	return Nums, nil
}

// 查询用户三端设备数量
// Auth: hzp
// source 1 全部  2 挖矿中的
type NodeTypeNums struct {
	Type        int   `db:"type" json:"type"`
	Status      int   `db:"status" json:"status"`
	TokenStatus int   `db:"token_status" json:"token_status"`
	Nums        int64 `db:"nums" json:"nums"`
}

func GetUserTypeNodeNums(uid int64) (res []NodeTypeNums, err error) {
	err = sqlx.Select(config.C.DB.DB, &res, "SELECT type, status, IFNULL(token_status, 0) as token_status, count(*) as nums FROM "+
		" mg_node where uid = ? AND status != 2 AND type = 2 group by type, status, token_status", uid)
	if err == sql.ErrNoRows {
		return res, nil
	}
	if err != nil {
		Log("error", uid, "查询用户三端设备数量uid=", uid, " &err=", err.Error())
		return res, err
	}
	return res, nil
}

//查询用户今日贡献流量
func GetUserTodayUpload(uid int64, Type int) (int64, error) {
	var sum sql.NullInt64
	err := sqlx.Get(config.C.DB.DB, &sum, `SELECT sum(f.up) FROM mg_node n LEFT JOIN mg_node_flow f ON f.node_id = n.node_id and f.type = ? WHERE n.uid = ? and n.type = ? AND f.time >= UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE))`, Type, uid, Type)
	if err == sql.ErrNoRows {
		err = nil
	}
	if err != nil {
		Log("error", uid, "查询用户今日贡献流量失败", err.Error())
	}
	return sum.Int64, err
}

//查询挖矿更新时间
func GetMiningInfoUpdateTime(uid int64, Type int) (createTime string, err error) {
	var t sql.NullString
	err = sqlx.Get(config.C.DB.DB, &t, `SELECT FROM_UNIXTIME(max(f.time), '%m/%d %H:%i') FROM mg_node_flow f LEFT JOIN mg_node n ON f.node_id = n.node_id and f.type = ? WHERE n.uid = ? and n.type = ?`, Type, uid, Type)
	if err == sql.ErrNoRows {
		err = nil
	}
	if err != nil {
		Log("error", uid, "查询挖矿更新时间失败", err.Error())
	}
	return t.String, err
}

/*
	routerSize	路由器贡献量
    linuxSize	奖励池贡献量
    cvnt		cvn数量
*/
type CvntCountInfo struct {
	RouterSize string  `json:"routerSize"`
	LinuxSize  string  `json:"linuxSize"`
	Cvnt       float64 `json:"cvnt"`
	NodeCount  int64   `json:"nodeCount"`
}

//查询路由器总贡献量(老数据)
func GetRouterOldUpload(uid int64) (upload int64, err error) {
	var sum sql.NullInt64
	var sqlStr string
	if uid > 0 {
		sqlStr = fmt.Sprintf("SELECT sum(old_upload_size) FROM router_user_old_data WHERE uid = %d", uid)
	} else {
		sqlStr = "SELECT sum(old_upload_size) FROM router_user_old_data"
	}
	err = sqlx.Get(config.C.DB.DB, &sum, sqlStr)

	if err == sql.ErrNoRows {
		err = nil
	}
	if err != nil {
		Log("error", "查询路由器累计贡献流量失败(老数据)", err.Error())
	}
	return sum.Int64, err
}

//查询用户路由器累计获得CVNT(老数据)
func GetUserOldRouterCvnt(uid int64) (cvnt float64, err error) {
	var sum sql.NullFloat64
	err = sqlx.Get(config.C.DB.DB, &sum, "SELECT sum(old_cvnt) FROM router_user_old_data WHERE uid = ?", uid)
	if err == sql.ErrNoRows {
		err = nil
	}
	if err != nil {
		Log("error", uid, "查询用户路由器累计获得CVNT失败", err.Error())
	}
	return sum.Float64, err
}

//查询新版挖矿节点累计贡献量
// Auth: hzp
func GetUserAllNodeUploadByUidAndNodeId(Uid, NodeId int64) (upload int64, err error) {
	db := config.C.DB.DB
	if NodeId > 0 {
		// 查询单节点数据
		err = sqlx.Get(db, &upload, "SELECT IFNULL(SUM(up), 0) FROM mg_node_payment WHERE node_id = ?", NodeId)
	} else {
		// 查询总的贡献量
		err = sqlx.Get(db, &upload, "SELECT IFNULL(SUM(up), 0) FROM mg_node_payment WHERE node_id in (SELECT node_id FROM mg_node where uid=?)", Uid)
	}
	return upload, err
}

//查询新版挖矿节点累计贡献量
// Auth: hzp
func GetDayUploadByUidAndNodeId(Uid, NodeId int64) (upload float64, err error) {
	db := config.C.DB.DB
	if NodeId > 0 {
		// 查询单节点今日贡献量
		err = sqlx.Get(db, &upload, "SELECT IFNULL(SUM(up), 0) FROM mg_node_flow WHERE node_id = ? AND `time`>= "+
			"UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE)) ", NodeId)
	} else {
		// 查询昨日uid总贡献量
		if Uid > 0 {
			//err = sqlx.Get(db, &upload, "SELECT IFNULL(SUM(up), 0) FROM mg_node_flow WHERE `time`< UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE))"+
			//	" AND `time`>= UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE) - INTERVAL 1 DAY) AND node_id in "+
			//	"(SELECT node_id FROM mg_node where uid=? AND `status` <> 2)", Uid)
			err = sqlx.Get(db, &upload, "SELECT IFNULL(Sum(up), 0) FROM mg_node_payment where "+
				" `date` = DATE_SUB(CURDATE(),INTERVAL 1 DAY) AND uid = ?", Uid)
		} else {
			err = sqlx.Get(db, &upload, "SELECT IFNULL(Sum(up), 0) FROM mg_node_payment where "+
				" `date` = DATE_SUB(CURDATE(),INTERVAL 1 DAY)")
			//err = sqlx.Get(db, &upload, "SELECT IFNULL(SUM(up), 0) FROM mg_node_flow WHERE `time`< UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE))"+
			//	" AND `time`>= UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE) - INTERVAL 1 DAY)")
		}
	}
	Log("info", "调用[GetDayUploadByUidAndNodeId]接口请求完成：")
	return upload, err
}

//查询总贡献量
func GetUserTotalUpload(uid int64, nodeType int) (upload int64, err error) {
	var sum sql.NullInt64
	var sqlStr string
	if uid > 0 {
		sqlStr = fmt.Sprintf("SELECT sum(f.up) FROM mg_node n LEFT JOIN mg_node_flow f ON f.node_id = n.node_id and n.type = %d WHERE n.uid = %d and f.type = %d", nodeType, uid, nodeType)
	} else {
		sqlStr = "SELECT sum(up) FROM mg_node_flow where type = " + strconv.Itoa(nodeType)
	}
	err = sqlx.Get(config.C.DB.DB, &sum, sqlStr)
	if err == sql.ErrNoRows {
		err = nil
	}
	if err != nil {
		Log("error", "查询累计贡献流量失败", err.Error())
	}
	return sum.Int64, err
}

//查询用户累计获得CVNT
//source 1累计获得  2昨日获得
func GetUserReceivedCvnt(uid int64, source int, nodeType int) (cvnt float64, err error) {
	var sum sql.NullFloat64
	if source == 1 {
		err = sqlx.Get(config.C.DB.DB, &sum, "SELECT sum(cvn) FROM mg_node_payment WHERE uid = ? AND status = 1 and type = ? ", uid, nodeType)
	} else {
		err = sqlx.Get(config.C.DB.DB, &sum, "SELECT sum(cvn) FROM mg_node_payment WHERE uid = ? AND status = 1 and type = ? AND create_time >= unix_timestamp(DATE_SUB(curdate(),INTERVAL 1 DAY))", uid, nodeType)
	}
	if err == sql.ErrNoRows {
		err = nil
	}
	if err != nil {
		Log("error", uid, "查询用户累计获得CVNT失败", err.Error())
	}
	return sum.Float64, err
}

type CheckNodeInfoResponse struct {
	DateStr      string  `json:"dateStr"`
	SuperNodeId  int64   `json:"superNodeId"`
	Up           float64 `json:"up"`
	Cvn          float64 `json:"cvn"`
	PledgeStatus int     `json:"pledgeStatus"`
	IncomeMode   int     `json:"incomeMode"`
	OnlineTime   int     `json:"onlineTime"`
	Uid          int64   `json:"uid"`
	NodeId       int64   `json:"nodeId"`
	Type         int     `json:"type"`
	Source       int     `json:"source"`
}

type RouterMiningInfoResponse struct {
	NodeId            int64   `db:"node_id" json:"nodeId"`
	Cvnt              float64 `db:"cvnt" json:"cvnt"`
	Up                string  `db:"up" json:"up"`
	Status            int     `db:"status" json:"status"`
	OnlineTime        int     `db:"online_time" json:"onlineTime"`
	Batch             int     `db:"batch" json:"batch"`
	TokenStatus       int     `db:"token_status" json:"token_status"`
	HistoryOnlineTime string  `db:"history_online_time" json:"history_online_time"`
	Name              string  `db:"name" json:"name"`
	Approved          int     `db:"approved" json:"approved"`
	HasStorage        int     `db:"storage" json:"hasStorage"`
	OnlineStatus      int     `db:"online_status" json:"-"`
	PublicIp          string  `db:"public_ip" json:"-"`
}

type RouterMiningInfo struct {
	NodeId            int64   `db:"node_id" json:"nodeId"`
	Cvnt              float64 `db:"cvnt" json:"cvnt"`
	Up                float64 `db:"up" json:"up"`
	Status            int     `db:"status" json:"status"`
	Type              int     `db:"type" json:"type"`
	OnlineTime        int     `db:"online_time" json:"onlineTime"`
	Batch             int     `db:"batch" json:"batch"`
	TokenStatus       int     `db:"token_status" json:"token_status"`
	HistoryOnlineTime string  `db:"history_online_time" json:"history_online_time"`
	Name              string  `db:"name" json:"name"`
	Approved          int     `db:"approved" json:"approved"`
	HasStorage        int     `db:"storage" json:"hasStorage"`
	OnlineStatus      int     `db:"online_status" json:"online_status"`
	PublicIp          string  `db:"public_ip" json:"-"`
}

//查询用户节点列表
func GetUserNodeInfoList(uid int64, Type, per, page int) (info []RouterMiningInfo, err error) {
	if per == 0 {
		err = sqlx.Select(config.C.DB.DB, &info, `SELECT t1.node_id, IFNULL(NAME,"") as name, IFNULL(approved,"") approved, storage, t1.token_status, t1.type, t1.history_online_time, t1.batch, t1.status, online_status, public_ip, IFNULL(SUM(t2.up)/1024/1024, 0.00) AS up 
FROM mg_node AS t1 LEFT JOIN mg_node_flow AS t2 ON t1.node_id=t2.node_id AND t2.time >=UNIX_TIMESTAMP(CURDATE()) WHERE t1.uid = ? AND t1.type =? AND t1.status != 2 GROUP BY t1.node_id order by t1.node_id desc`, uid, Type)
	} else {
		start := (page - 1) * per
		err = sqlx.Select(config.C.DB.DB, &info, `SELECT t1.node_id, IFNULL(NAME,"") as name, IFNULL(approved,"") approved, storage, t1.token_status, t1.type, t1.history_online_time, t1.batch, t1.status, online_status, public_ip, IFNULL(SUM(t2.up)/1024/1024, 0.00) AS up 
FROM mg_node AS t1 LEFT JOIN mg_node_flow AS t2 ON t1.node_id=t2.node_id AND t2.time >=UNIX_TIMESTAMP(CURDATE()) WHERE t1.uid = ? AND t1.type =? AND t1.status != 2 GROUP BY t1.node_id order by t1.node_id desc limit ?,?`, uid, Type, start, per)
	}
	if err != nil {
		Log("error", "获取用户挖矿节点列表失败！", err.Error())
	}
	return
}

func GetBatchNum(uid int64) (int64, error) {
	var res sql.NullInt64
	err := sqlx.Get(config.C.DB.DB, &res, "SELECT COUNT(*) FROM mg_node WHERE batch = 3 AND uid = ?", uid)
	if err != nil {
		Log("error", "GetBatchNum失败 ", uid, err.Error())
	}
	return res.Int64, err
}

func GetBatchStatus(uid int64) (status int, err error) {
	err = sqlx.Get(config.C.DB.DB, &status, "SELECT IF(SUM(cvn)>0, 1, 0) FROM mg_node_payment WHERE uid = ? AND DATE_FORMAT(date, '%Y%m') = DATE_FORMAT(CURDATE(), '%Y%m') AND type = 4", uid)
	if err != nil {
		Log("error", "GetBatchStatus ", uid, err.Error())
	}
	return
}

// 路由器用户折线图
func GetClientRouterUserData(NodeId, SearchType, nodeType int) (re []ChartRouter, err error) {
	db := config.C.DB.DB

	// 1时报表 2日报表
	switch SearchType {
	case 1:
		err = sqlx.Select(db, &re, "SELECT FROM_UNIXTIME(time, '%Y/%m/%d %H:00') AS time, IFNULL(up, '0') AS total "+
			"FROM mg_node_flow where node_id = ? AND type = ? AND time >= UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE)) ORDER BY time DESC", NodeId, nodeType)
		break
	case 2:
		err = sqlx.Select(db, &re, "SELECT t1.date AS time, t1.up*1024*1024 AS total, IFNULL(t1.cvn, 0) AS cvnt, t1.online_time AS onlineTime, "+
			" ifnull(t2.status,1) AS status FROM mg_node_payment t1 LEFT JOIN mg_user_payment t2 ON t1.uid = t2.uid AND t2.type = ? AND t1.date = t2.date WHERE "+
			" t1.node_id = ? AND t1.type = ? ORDER BY TIME DESC LIMIT 200", nodeType, NodeId, nodeType)
		break
	}
	if err != nil {
		return re, err
	}

	return
}
